﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FineSoft.Models
{
	public class Document : Model, System.Runtime.Serialization.ISerializable
	{
		protected int _ComponentAutoId;
		public string ComponentAutoId
		{
			get
			{
				return "C" + this._ComponentAutoId++;
			}
		}

		private string _Title = "";
		public string Title
		{
			get
			{
				return this._Title;
			}
			set
			{
				this.RaisePropertyChanging("Title");
				this._Title = value;
				this.RaisePropertyChanged("Title");
			}
		}

		private System.Collections.Generic.List<HtmlElement> _HeaderItems;
		public System.Collections.Generic.List<HtmlElement> HeaderItems
		{
			get
			{
				if (this._HeaderItems == null)
				{
					this._HeaderItems = new List<HtmlElement>();
					this._HeaderItems.Add(this.ExtJsStyleSheet);
					this._HeaderItems.Add(this.ExtJsScript);
					this._HeaderItems.Add(this.DesignerScript);
					this._HeaderItems.Add(this.UserScript);
				}
				return this._HeaderItems;
			}
		}

		private StyleSheetLink _ExtJsStyleSheet;
		public StyleSheetLink ExtJsStyleSheet
		{
			get
			{
				if (this._ExtJsStyleSheet == null)
				{
					this._ExtJsStyleSheet = new StyleSheetLink();
					this._ExtJsStyleSheet.Href = @"G:\Libraries\ext-4.2.2.1144\resources\css\ext-all.css";
				}
				return this._ExtJsStyleSheet;
			}
		}

		private ScriptLink _ExtJsScript;
		public ScriptLink ExtJsScript
		{
			get
			{
				if (this._ExtJsScript == null)
				{
					this._ExtJsScript = new ScriptLink();
					this._ExtJsScript.Src = @"G:\Libraries\ext-4.2.2.1144\ext-all-debug.js";
				}
				return this._ExtJsScript;
			}
		}

		private ScriptLink _DesignerScript;
		public ScriptLink DesignerScript
		{
			get
			{
				if (this._DesignerScript == null)
				{
					this._DesignerScript = new ScriptLink();
					this._DesignerScript.Src = System.IO.Path.GetFileNameWithoutExtension(this.File.Path) + ".designer.js";
				}
				return this._DesignerScript;
			}
		}

		public File File { get; set; }

		private ScriptLink _EditorDesignerScript;
		public ScriptLink EditorDesignerScript
		{
			get
			{
				if (this._EditorDesignerScript == null)
				{
					this._EditorDesignerScript = new ScriptLink();
					this._EditorDesignerScript.Src = System.IO.Path.GetFileNameWithoutExtension(this.File.Path) + ".editor.designer.js";
				}
				return this._EditorDesignerScript;
			}
		}

		private ScriptLink _UserScript;
		public ScriptLink UserScript
		{
			get
			{
				if (this._UserScript == null)
				{
					this._UserScript = new ScriptLink();
					this._UserScript.Src = System.IO.Path.GetFileNameWithoutExtension(this.File.Path) + ".js";
				}
				return this._UserScript;
			}
		}

		private ComponentObject _ViewPortObject;
		public ComponentObject ViewPortObject
		{
			get
			{
				if (this._ViewPortObject == null)
				{
					this._ViewPortObject = new ComponentObject();
					{
						this._ViewPortObject.Type = (ComponentClass)InitialData.GetClass("Ext.container.Viewport");
						this._ViewPortObject.Id = "ViewPort";
					}
				}
				return this._ViewPortObject;
			}
		}

		private ComponentObject[] _AllComponents;
		public ComponentObject[] AllComponents
		{
			get
			{
				if (this._AllComponents == null)
				{
					System.Collections.Generic.List<ComponentObject> components = this.GetComponents(this.ViewPortObject.Containers);
					components.Insert(0, this.ViewPortObject);
					this._AllComponents = components.ToArray();
				}
				return this._AllComponents;
			}
		}

		public string[] AllComponentIds
		{
			get
			{
				return this.AllComponents.Select(c => (string)c.Id).ToArray();
			}
		}

		private System.Collections.Generic.List<ComponentObject> GetComponents(System.Collections.Generic.Dictionary<ContainerConfig, System.Collections.Generic.List<ComponentObject>> containers)
		{
			System.Collections.Generic.List<ComponentObject> components = new List<ComponentObject>();
			foreach(ContainerConfig config in containers.Keys)
				foreach (ComponentObject component in containers[config])
				{
					components.Add(component);
					if (((ComponentClass)component.Type).IsContainer)
						components.AddRange(this.GetComponents(component.Containers));
				}
			return components;
		}

		public ComponentObject AddComponent(FineSoft.Models.ComponentObject container, FineSoft.Models.ComponentClass type)
		{
			FineSoft.Models.ComponentObject component = new Models.ComponentObject();
			component.Type = type;
			component.Id = this.ComponentAutoId;
			component.ParentComponent = container;
			container.SelectedContainer.Value.Add(component);

			this._AllComponents = null;
			return component;
		}

		public Document(/*string filePath*/)
		{
			//this.FilePath = filePath;
		}

		public void Save()
		{
			HtmlTemplate htmlTemplate = new HtmlTemplate();
			htmlTemplate.Title = this.Title;
			htmlTemplate.HeaderItems = this.HeaderItems;
			System.IO.File.WriteAllText(this.File.Path, htmlTemplate.TransformText(), System.Text.Encoding.UTF8);

			DesignerTemplate designerTemplate = new DesignerTemplate();
			designerTemplate.ViewPortObject = this.ViewPortObject;
			System.IO.File.WriteAllText(this.File.DesignerFilePath, designerTemplate.TransformText(), System.Text.Encoding.UTF8);

			//System.IO.File.WriteAllText(this.DesignerFilePath,this.ViewPortObject.ConfigsString,
		}

		public void OpenForEditor()
		{
			HtmlTemplate htmlTemplate = new HtmlTemplate();
			htmlTemplate.DesignMode = true;
			htmlTemplate.Title = this.Title;

			HtmlElement[] headerItems = this.HeaderItems.ToArray();
			for (int i = 0; i < headerItems.Length; i++)
				if (headerItems[i] == this.DesignerScript)
					headerItems[i] = this.EditorDesignerScript;
			htmlTemplate.HeaderItems = headerItems;

			System.IO.File.WriteAllText(this.File.EditorFilePath, htmlTemplate.TransformText(), System.Text.Encoding.UTF8);

			DesignerTemplate designerTemplate = new DesignerTemplate();
			designerTemplate.DesignMode = true;
			designerTemplate.ViewPortObject = this.ViewPortObject;
			System.IO.File.WriteAllText(this.File.EditorDesignerFilePath, designerTemplate.TransformText(), System.Text.Encoding.UTF8);
		}

		#region ISerializable 成员

		public Document(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
		{
			this._ComponentAutoId = info.GetInt32("ComponentAutoId");
			this._HeaderItems = new List<HtmlElement>();
			int count = info.GetInt32("HeaderItemCount");
			for (int i = 0; i < count; i++)
			{
				HtmlElement element = (HtmlElement)info.GetValue("HeaderItem_Value" + i, System.Type.GetType(info.GetString("HeaderItem_Type" + i)));
				switch (element.TagName)
				{
					case "ExtJsStyleSheet":
						element = this.ExtJsStyleSheet;
						break;
					case "ExtJsScript":
						element = this.ExtJsScript;
						break;
					case "DesignerScript":
						element = this.DesignerScript;
						break;
					case "UserScript":
						element = this.UserScript;
						break;
				}
				this.HeaderItems.Add(element);
			}
			this._ViewPortObject = (ComponentObject)info.GetValue("ViewPortObject", typeof(ComponentObject));
		}

		void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
		{
			info.AddValue("ComponentAutoId", this._ComponentAutoId);
			info.AddValue("HeaderItemCount", this.HeaderItems.Count);
			for (int i = 0; i < this.HeaderItems.Count; i++)
			{
				HtmlElement element = this.HeaderItems[i];
				string typeName = "HeaderItem_Type" + i;
				string valueName = "HeaderItem_Value" + i;
				if (element == this.ExtJsStyleSheet)
				{
					info.AddValue(typeName, typeof(HtmlElement).GetName());
					info.AddValue(valueName, new HtmlElement("ExtJsStyleSheet"));
					continue;
				}
				if (element == this.ExtJsScript)
				{
					info.AddValue(typeName, typeof(HtmlElement).GetName());
					info.AddValue(valueName, new HtmlElement("ExtJsScript"));
					continue;
				}
				if (element == this.DesignerScript)
				{
					info.AddValue(typeName, typeof(HtmlElement).GetName());
					info.AddValue(valueName, new HtmlElement("DesignerScript"));
					continue;
				}
				if (element == this.UserScript)
				{
					info.AddValue(typeName, typeof(HtmlElement).GetName());
					info.AddValue(valueName, new HtmlElement("UserScript"));
					continue;
				}
				info.AddValue(typeName, element.GetType().GetName());
				info.AddValue(valueName, element);
			}
			info.AddValue("ViewPortObject", this.ViewPortObject);
		}

		#endregion
	}
}